package collector.core.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileUtil {
	private static Logger _log = LoggerFactory.getLogger(FileUtil.class);

	public static final String LS = System.getProperty("line.separator");
	public static final String FS = System.getProperty("file.separator");

	public static void main(String[] args) {
		// FileUtil.doTestCopyBytes();
		_log.info("Job States :: " + FileUtil.doTestReadWrite());
	}

	public static String doTestReadWrite() {

		String resMsg = "";
		String encodeing = "utf-8";
		String saveFileStr = "files/textfile-test-status-5-encoding.txt";

		try {
			String statusStr = "Test Status|2012-09-12 12:00:00|UTF-8용^한글^입력|On|Off|Succ";

			_log.info("Test Save Status to File...");
			writeTextFile(saveFileStr, statusStr, encodeing);

			_log.info("Test Read Status from File...");
			resMsg = readTextFile(saveFileStr, encodeing);
			_log.info("read From " + saveFileStr + " contents is [" + resMsg
					+ "]");
			_log.info("Test End...");

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return resMsg;
	}

	public static void doTestCopyBytes() {

		String encodeing = "utf-8";
		String FileStr1 = "files/textfile-test-status-1-strFile.txt";
		String FileStr2 = "files/textfile-test-status-2-objFile.txt";
		String FileStr3 = "files/textfile-test-status-3-copy.txt";
		String FileStr4 = "files/textfile-test-status-4-encoding.txt";

		try {
			String statusStr = "Test Status|2012-09-12 12:00:00|UTF-8용^한글^입력|On|Off|Succ";

			_log.info("Test Save Status to File...");
			writeTextFile(FileStr1, statusStr, encodeing);
			File f2 = new File(FileStr2);
			writeTextFile(f2, statusStr, encodeing);

			_log.info("Test Read Status from File...");
			_log.info("read From " + FileStr1 + " contents is ["
					+ readTextFile(FileStr1, encodeing) + "]");
			_log.info("read From " + FileStr2 + " contents is ["
					+ readTextFile(f2, encodeing) + "]");

			_log.info("Test Copy file to File...");
			File f3 = new File(FileStr3);
			copyBytes(new FileInputStream(f2), new FileOutputStream(f3),
					f2.length());
			_log.info("done Copy and read From " + FileStr3 + " contents is ["
					+ readTextFile(f3, "utf-8") + "]");

			encodeing = "CP949";
			_log.info("read [encoding:" + encodeing + "] From " + FileStr3
					+ " contents is [" + readTextFile(f3, encodeing) + "]");

			_log.info("Test cp949 Save & read Status to File...");
			writeTextFile(FileStr4, statusStr, encodeing);
			_log.info("read From " + FileStr4 + " contents is ["
					+ readTextFile(FileStr4, encodeing) + "]");

			_log.info("Test End...");

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * <pre>
	 * Method : FileUtil.readTextFile()
	 * 	encoding으로 생성된 파일(File Object)에서 내용을 읽음
	 * <br>
	 * 	return type of String
	 * <br>
	 * @param file
	 * @param encoding
	 * @return
	 * @throws IOException
	 * </pre>
	 */
	public static String readTextFile(File file, String encoding)
			throws IOException {
		InputStream in = null;
		try {
			in = new FileInputStream(file);
			return IOUtils.toString(in, encoding);
		} finally {
			IOUtils.closeQuietly(in);
		}
	}

	/**
	 * <pre>
	 * Method : FileUtil.readTextFile()
	 * 	encoding으로 생성된 파일(String File Path/Name)에서 내용을 읽음
	 * <br>
	 * 	return type of String
	 * <br>
	 * @param filename
	 * @param encoding
	 * @return
	 * @throws IOException
	 * </pre>
	 */
	public static String readTextFile(String filename, String encoding)
			throws IOException {
		return readTextFile(new File(filename), encoding);
	}

	/**
	 * <pre>
	 * Method : FileUtil.writeTextFile()
	 * 	encoding에 따른 Data가 기록된 파일(File Object)을 생성
	 * <br>
	 * 	return type of void
	 * <br>
	 * @param file
	 * @param data
	 * @param encoding
	 * @throws IOException
	 * </pre>
	 */
	public static void writeTextFile(File file, String data, String encoding)
			throws IOException {
		FileUtils.writeStringToFile(file, data, encoding);
	}

	/**
	 * <pre>
	 * Method : FileUtil.writeTextFile()
	 * 	encoding에 따른 Data가 기록된 파일(String File Path/Name)을 생성
	 * <br>
	 * 	return type of void
	 * <br>
	 * @param filename
	 * @param data
	 * @param encoding
	 * @throws IOException
	 * </pre>
	 */
	public static void writeTextFile(String filename, String data,
			String encoding) throws IOException {
		writeTextFile(new File(filename), data, encoding);
	}

	/**
	 * <pre>
	 * Method : FileUtil.copyBytes()
	 * 	InputStream에서 OutputStream으로 정의된 길이만큼 Bytes 복사
	 * <br>
	 * 	return type of void
	 * <br>
	 * @param is
	 * @param os
	 * @param lengthEd
	 * @throws IOException
	 * </pre>
	 */
	public static void copyBytes(InputStream is, OutputStream os, long lengthEd)
			throws IOException {
		int buffSize = 1024 * 1024; // 1024*4;
		byte buf[] = new byte[buffSize];
		try {
			long totalWrite = 0;
			int bytesRead = is.read(buf);
			while (bytesRead >= 0) {
				if (lengthEd > 0) {
					long byteLeft = lengthEd - totalWrite;
					if (bytesRead >= byteLeft) {
						os.write(buf, 0, (int) (byteLeft));
						// os.flush();
						return;
					}
					totalWrite += bytesRead;
				}
				os.write(buf, 0, bytesRead);
				bytesRead = is.read(buf);
			}
			// os.flush();
		} finally {
		}
	}

	public static void copyBytes(String frFilename, String toFilename)
			throws IOException {
		File f2 = new File(frFilename);
		File f3 = new File(toFilename);
		copyBytes(new FileInputStream(f2), new FileOutputStream(f3),
				f2.length());
	}

	/**
	 * <pre>
	 * Method : FileUtil.copyBytes()
	 * 	path에 있는 frFilename와 같은 파일을 toFilename로 Bytes 복사
	 * <br>
	 * 	return type of void
	 * <br>
	 * @param path
	 * @param frFilename
	 * @param String
	 * @param fileNameExtension
	 * @throws IOException
	 * </pre>
	 */
	@SuppressWarnings("rawtypes")
	public static void copyBytes(String path, String frFilename, String toFilename, String fileNameExtension) throws IOException {
		String fileNumber;
		List pathFileList = FileUtil.getPathFileList(path);
		for (int i = 0; i < pathFileList.size(); i++) {
			if (pathFileList.get(i).toString().indexOf(frFilename) > 0) {
				fileNumber = pathFileList.get(i).toString().substring((pathFileList.get(i).toString().length() - 14), (pathFileList.get(i).toString().length() - 4));
				FileUtil.copyBytes(pathFileList.get(i).toString(), toFilename + fileNumber + fileNameExtension);
			}
		}
	}

	/**
	 * 파일을 확인하는 메소드
	 * 
	 * @param fileName
	 * @return
	 */
	public static Boolean checkFile(String fileName) {
		File f1 = new File(fileName);

		if (f1.exists()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 파일을 생성하는 메소드
	 * 
	 * @param fileName
	 */
	public static void makeFile(String fileName) {
		File f1 = new File(fileName);
		try {
			f1.createNewFile();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static void renameFile(String source, String target) {
		File f1 = new File(source);
		File f2 = new File(target);
		
		try {
			f1.renameTo(f2);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 파일을 삭제하는 메소드
	 * 
	 * @param fileName
	 */
	public static void deleteFile(String fileName) {
		File f1 = new File(fileName);
		f1.delete();
	}

	@SuppressWarnings("rawtypes")
	public static void deleteFile(String fileName, String path) {
		List pathFileList = FileUtil.getPathFileList(path);
		if (pathFileList == null)
			return;
		for (int i = 0; i < pathFileList.size(); i++) {
			if (pathFileList.get(i).toString().indexOf(fileName) > 0) {
				FileUtil.deleteFile(pathFileList.get(i).toString());
			}
		}
	}

	/**
	 * 파일을 복사하는 메소드
	 * 
	 * @param source
	 * @param target
	 */
	public static void copyChannel(String source, String target) {
		// 복사 대상이 되는 파일 생성
		File sourceFile = new File(source);

		// 스트림, 채널 선언
		FileInputStream inputStream = null;
		FileOutputStream outputStream = null;
		FileChannel fcin = null;
		FileChannel fcout = null;

		try {
			// 스트림 생성
			inputStream = new FileInputStream(sourceFile);
			outputStream = new FileOutputStream(target);
			// 채널 생성
			fcin = inputStream.getChannel();
			fcout = outputStream.getChannel();

			// 채널을 통한 스트림 전송
			long size = fcin.size();
			fcin.transferTo(0, size, fcout);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 자원 해제
			try {
				fcout.close();
			} catch (IOException ioe) {
			}
			try {
				fcin.close();
			} catch (IOException ioe) {
			}
			try {
				outputStream.close();
			} catch (IOException ioe) {
			}
			try {
				inputStream.close();
			} catch (IOException ioe) {
			}
		}
	}

	/**
	 * 파일을 이동하는 메소드
	 * 
	 * @param inFileName
	 * @param outFileName
	 */
	public static void moveFile(String inFileName, String outFileName) {
		try {
			FileInputStream fis = new FileInputStream(inFileName);
			FileOutputStream fos = new FileOutputStream(outFileName);

			int data = 0;
			while ((data = fis.read()) != -1) {
				fos.write(data);
			}
			fis.close();
			fos.close();

			deleteFile(inFileName);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 디렉토리의 파일 리스트를 읽는 메소드
	 * 
	 * @param dirPath
	 * @return
	 */
	public static List<File> getPathFileList(String dirPath) {
		List<File> dirFileList = null;
		File dir = new File(dirPath);

		if (dir.exists()) {
			File[] files = dir.listFiles();

			dirFileList = Arrays.asList(files);
		}
		return dirFileList;
	}

	/**
	 * 디렉토리 존재 확인 및 생성
	 * 
	 * @param url
	 */
	public static void directoryCheck(String path) {
		File directory = new File(path);
		if (!directory.isDirectory()) {
			directory.mkdirs();
		}
	}

	/**
	 * 파일 넘버링 생성
	 * 
	 * @param fileCount
	 * @return
	 */
	public static String genFileNumber(int fileCount) {
		String fileNumber = "000" + fileCount;
		fileNumber = fileNumber.substring((fileNumber.length() - 4),
				fileNumber.length());
		fileNumber = "_" + fileNumber;

		return fileNumber;
	}

	/**
	 * <pre>
	 * Method : FileUtil.createFile()
	 * 
	 * <br>
	 * 	return type of File
	 * <br>
	 * @param pFname
	 * @return
	 * </pre>
	 */
	public static File createFile(String pFname) {
		File f = null;
		try {
			f = new File(pFname);
			// System.out.println("pFname : ABS="+f.getAbsolutePath() + " CAN="
			// + f.getCanonicalPath() + " PAR=" + f.getParent() + " PATH=" +
			// f.getPath() );
			if (!f.exists()) {
				if (!f.createNewFile())
					System.out.println("Create File : " + pFname);
			}
		} catch (Exception e) {
			// 생성 실패시
			String srcfname = f.getAbsolutePath();
			String drv = StringUtil.getIndexString(srcfname, ":", 0);
			srcfname = StringUtil.replaceAll(srcfname, drv + ":", "C:");
			System.out.println("Change Drive Char : " + pFname + " to "
					+ srcfname);
			f = new File(srcfname);
			if (!f.exists()) {
				try {
					if (!f.createNewFile())
						System.out.println("Create File : " + srcfname);
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
		return f;
	}
}
